package com.xiaohua.api.utils.security;

import com.xiaohua.api.common.constants.TextInConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.security.MessageDigest;
import java.util.Base64;
import java.nio.charset.StandardCharsets;

/**
 * TextIn 缓存工具类
 *
 * @author 小花
 * @date 2025-04-03
 */
@Component
public class TextInCacheUtils {
    
    private static final Logger log = LoggerFactory.getLogger(TextInCacheUtils.class);
    
    /**
     * 缓存条目，包含结果和时间戳
     */
    public static class CacheEntry {
        private String result;
        private long timestamp;
        
        public CacheEntry(String result) {
            this.result = result;
            this.timestamp = System.currentTimeMillis();
        }
        
        public String getResult() {
            return result;
        }
        
        public long getTimestamp() {
            return timestamp;
        }
    }
    
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    
    /**
     * 计算图片数据的哈希值
     * 
     * @param imageBase64 Base64编码的图片数据
     * @param apiType API类型
     * @return 哈希值
     */
    public static String calculateImageHash(String imageBase64, String apiType) {
        try {
            // 只使用数据的前10KB来计算哈希，避免过长
            String dataToHash = imageBase64;
            if (dataToHash.length() > 10240) {
                dataToHash = dataToHash.substring(0, 10240);
            }
            dataToHash += apiType; // 添加API类型到哈希计算中，确保不同API的相同图片有不同的缓存键
            
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hash = digest.digest(dataToHash.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(hash);
        } catch (Exception e) {
            log.error("计算图片哈希值失败", e);
            return null;
        }
    }
    
    /**
     * 计算URL的哈希值
     * 
     * @param imageUrl 图片URL
     * @param apiType API类型
     * @return 哈希值
     */
    public static String calculateUrlHash(String imageUrl, String apiType) {
        try {
            String dataToHash = imageUrl + apiType; // 使用URL和API类型组合作为哈希输入
            
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hash = digest.digest(dataToHash.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(hash);
        } catch (Exception e) {
            log.error("计算URL哈希值失败", e);
            return null;
        }
    }
    
    /**
     * 从缓存获取结果
     * 
     * @param cache 缓存Map
     * @param key 缓存键
     * @return 缓存结果，如果不存在或过期则返回null
     */
    public static String getFromCache(ConcurrentHashMap<String, CacheEntry> cache, String key) {
        if (key == null || key.isEmpty()) {
            return null;
        }
        
        CacheEntry entry = cache.get(key);
        if (entry == null) {
            return null;
        }
        
        // 检查缓存是否过期，默认24小时
        long now = System.currentTimeMillis();
        long expireTimeMs = 24 * 60 * 60 * 1000; // 24小时过期
        if (now - entry.timestamp > expireTimeMs) {
            cache.remove(key);
            return null;
        }
        
        return entry.result;
    }
    
    /**
     * 将结果存入缓存
     * 
     * @param cache 缓存Map
     * @param key 缓存键
     * @param result 缓存结果
     */
    public static void putIntoCache(ConcurrentHashMap<String, CacheEntry> cache, String key, String result) {
        if (key == null || key.isEmpty() || result == null) {
            return;
        }
        
        cache.put(key, new CacheEntry(result));
    }
    
    /**
     * 清理过期的缓存条目
     * 
     * @param cache 缓存Map
     * @return 清理的条目数量
     */
    public static int cleanExpiredEntries(ConcurrentHashMap<String, CacheEntry> cache) {
        if (cache == null || cache.isEmpty()) {
            return 0;
        }
        
        int sizeBefore = cache.size();
        long now = System.currentTimeMillis();
        long expireTimeMs = 24 * 60 * 60 * 1000; // 24小时过期
        
        // 使用Java 8 Stream API处理
        cache.entrySet().removeIf(entry -> now - entry.getValue().timestamp > expireTimeMs);
        
        int sizeAfter = cache.size();
        return sizeBefore - sizeAfter;
    }
    
    /**
     * 保存身份证信息到缓存
     *
     * @param key 关键字（通常是身份证号码）
     * @param value 身份证识别结果
     */
    public void saveIdCardCache(String key, Object value) {
        if (key == null || key.isEmpty() || value == null) {
            return;
        }
        
        try {
            String cacheKey = TextInConstants.CacheConstants.ID_CARD_CACHE_PREFIX + key;
            redisTemplate.opsForValue().set(cacheKey, value, 
                    TextInConstants.CacheConstants.DEFAULT_CACHE_SECONDS, TimeUnit.SECONDS);
            log.debug("保存身份证缓存成功: {}", maskString(cacheKey));
        } catch (Exception e) {
            log.error("保存身份证缓存失败: {}", e.getMessage(), e);
        }
    }
    
    /**
     * 从缓存获取身份证信息
     *
     * @param key 关键字（通常是身份证号码）
     * @return 身份证识别结果
     */
    public Object getIdCardCache(String key) {
        if (key == null || key.isEmpty()) {
            return null;
        }
        
        try {
            String cacheKey = TextInConstants.CacheConstants.ID_CARD_CACHE_PREFIX + key;
            Object result = redisTemplate.opsForValue().get(cacheKey);
            if (result != null) {
                log.debug("从缓存获取身份证信息: {}", maskString(cacheKey));
            }
            return result;
        } catch (Exception e) {
            log.error("获取身份证缓存失败: {}", e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 保存银行卡信息到缓存
     *
     * @param key 关键字（通常是银行卡号）
     * @param value 银行卡识别结果
     */
    public void saveBankCardCache(String key, Object value) {
        if (key == null || key.isEmpty() || value == null) {
            return;
        }
        
        try {
            String cacheKey = TextInConstants.CacheConstants.BANK_CARD_CACHE_PREFIX + key;
            redisTemplate.opsForValue().set(cacheKey, value, 
                    TextInConstants.CacheConstants.DEFAULT_CACHE_SECONDS, TimeUnit.SECONDS);
            log.debug("保存银行卡缓存成功: {}", maskString(cacheKey));
        } catch (Exception e) {
            log.error("保存银行卡缓存失败: {}", e.getMessage(), e);
        }
    }
    
    /**
     * 从缓存获取银行卡信息
     *
     * @param key 关键字（通常是银行卡号）
     * @return 银行卡识别结果
     */
    public Object getBankCardCache(String key) {
        if (key == null || key.isEmpty()) {
            return null;
        }
        
        try {
            String cacheKey = TextInConstants.CacheConstants.BANK_CARD_CACHE_PREFIX + key;
            Object result = redisTemplate.opsForValue().get(cacheKey);
            if (result != null) {
                log.debug("从缓存获取银行卡信息: {}", maskString(cacheKey));
            }
            return result;
        } catch (Exception e) {
            log.error("获取银行卡缓存失败: {}", e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 保存营业执照信息到缓存
     *
     * @param key 关键字（通常是统一社会信用代码）
     * @param value 营业执照识别结果
     */
    public void saveBusinessLicenseCache(String key, Object value) {
        if (key == null || key.isEmpty() || value == null) {
            return;
        }
        
        try {
            String cacheKey = TextInConstants.CacheConstants.BUSINESS_LICENSE_CACHE_PREFIX + key;
            redisTemplate.opsForValue().set(cacheKey, value, 
                    TextInConstants.CacheConstants.DEFAULT_CACHE_SECONDS, TimeUnit.SECONDS);
            log.debug("保存营业执照缓存成功: {}", maskString(cacheKey));
        } catch (Exception e) {
            log.error("保存营业执照缓存失败: {}", e.getMessage(), e);
        }
    }
    
    /**
     * 从缓存获取营业执照信息
     *
     * @param key 关键字（通常是统一社会信用代码）
     * @return 营业执照识别结果
     */
    public Object getBusinessLicenseCache(String key) {
        if (key == null || key.isEmpty()) {
            return null;
        }
        
        try {
            String cacheKey = TextInConstants.CacheConstants.BUSINESS_LICENSE_CACHE_PREFIX + key;
            Object result = redisTemplate.opsForValue().get(cacheKey);
            if (result != null) {
                log.debug("从缓存获取营业执照信息: {}", maskString(cacheKey));
            }
            return result;
        } catch (Exception e) {
            log.error("获取营业执照缓存失败: {}", e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 删除缓存
     *
     * @param cacheKey 缓存键
     */
    public void deleteCache(String cacheKey) {
        if (cacheKey == null || cacheKey.isEmpty()) {
            return;
        }
        
        try {
            redisTemplate.delete(cacheKey);
            log.debug("删除缓存成功: {}", maskString(cacheKey));
        } catch (Exception e) {
            log.error("删除缓存失败: {}", e.getMessage(), e);
        }
    }
    
    /**
     * 掩码显示字符串，保护敏感信息
     */
    private String maskString(String input) {
        if (input == null || input.length() <= 8) {
            return "******";
        }
        return input.substring(0, 4) + "******" + input.substring(input.length() - 4);
    }
} 